home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
167_01
/
bu.c
< prev
next >
Wrap
Text File
|
1985-08-19
|
30KB
|
984 lines
/* BU.C - A File Backup Utility for CP/M-80 & CP/M-86
*
* Copyright: Ian Ashdown
* byHeart Software
* 2 - 2016 West First Avenue
* Vancouver, B.C. V6J 1G8
* Canada
*
* Acknowledgment: DeSmet C code and suggestions for program
* improvement courtesy of Dr. Dobb's Journal
* Contributing Editor Anthony Skjellum
*
* Version: 1.2 Written for Aztec CII v1.06b (CP/M-80)
* and DeSmet C88 v2.2 (CP/M-86)
*
* Date: December 31st, 1983 (Version 1.0)
* September 7th, 1984 (Version 1.1)
* November 7th, 1985 (Version 1.2)
*
* Version Modifications:
*
* 24/09/84 - "read()" and "write()" accept maximum of 32767
* bytes, not 32768. Functions "copy_file()" and
* "verify_file()" modified accordingly.
* 07/11/85 - function "copy_file()" incorrectly copied file
* when last invocation of "read()" exactly filled
* input file buffer or input file was of zero length.
* Statement added to break copy loop on "read()"
* returning zero.
*
* BU utilizes the undocumented "archive" file attribute feature
* of CP/M-80 Versions 2.x and CP/M-86 to automatically detect
* files that have been changed since the disk was last "backed
* up" and copy them (with verification) to a backup disk. This
* program performs the same action as the "A" option of PIP
* under Digital Research's MP/M 2, for which the Archive
* attribute is documented.
*
* Usage: BU x[:afn] y [-AFHQSn]
*
* where x = drive name of disk to be backed up
* y = drive name of backup disk
*
* and the optional arguments are:
*
* -A All files, regardless of status
* -F Fast copy (without verification)
* -H Hard disk (files may be split)
* -Q Query each file before backup
* -S System attribute copied to backup
* -n Backup USER 'n' files only (0-31)
* afn Any legal CP/M ambiguous fileref
* (can only be used with -n option)
*/
#include "stdio.h"
#include "ctype.h" /* Contains macro for "isdigit()" */
/*** DEFINITIONS ***/
#define AZTEC 1 /* Aztec CII v1.06b (CP/M-80) */
#define DESMET 0 /* DeSmet C88 v2.2 (CP/M-86) */
#if DESMET
#define movmem(src,dest,len) _mov(len,src,dest)
#endif
#define ERROR -1
#define DEL -1 /* Deleted fileref flag */
#define ALL -1 /* All user numbers flag */
#define TRUE -1
#define FALSE 0
#define SUCCESS 0
#define O_RDONLY 0
#define USER_ERR 0 /* Specified fileref must only be used
with -number command-line option */
#define BAD_FREF 1 /* Illegal file reference */
#define BAD_ARGS 2 /* Illegal command line */
#define BAD_OPT 3 /* Illegal option */
#define BAD_USER 4 /* Illegal user number */
#define BAD_DRV 5 /* Illegal drive names */
#define SAME_DRV 6 /* Same drive name for output as input */
#define OPN_ERR 8 /* File open error */
#define READ_ERR 9 /* File read error */
#define CLS_ERR 10 /* File close error */
#define BAD_VFY 11 /* File verify error */
#define DIR_IO 6 /* BDOS Direct I/O service */
#define RESET_DRV 13 /* BDOS Reset All Drives service */
#define SEL_DRV 14 /* BDOS Select Drive service */
#define SRCH_F 17 /* BDOS Search Next service */
#define SRCH_N 18 /* BDOS Search Next service */
#define GET_DRV 25 /* BDOS Get Default Drive service */
#define SET_DMA 26 /* BDOS Set DMA Address service */
#define SET_ATT 30 /* BDOS Set File Attributes service */
#define USER_CODE 32 /* BDOS Get/Set User Code service */
#define MAX_USER 32 /* 32 user codes under CP/M (see DR's
documentation for BDOS Service 32) */
/*** GLOBAL VARIABLES ***/
char ent_drv, /* Entry drive code */
ent_user, /* Entry user code */
cur_user; /* Current user code */
/*** MAIN BODY OF CODE ***/
main(argc,argv)
int argc;
char *argv[];
{
char in_dsk, /* Drive name of input disk */
out_dsk, /* Drive name of output (backup) disk */
in_drv, /* Drive code of input disk */
out_drv, /* Drive code of output disk */
seg_no, /* Segment number for split files */
in_file[15], /* Fileref of current input file */
out_file[15], /* Fileref of current output file */
c, /* Scratch variable */
*s, /* Scratch string pointer */
*buffer, /* Pointer to directory entry returned */
/* by "srch_file()" */
*srch_file(),
*malloc();
/* File control blocks of current input and output files */
static char in_fcb[33], /* (Automatically initialized */
out_fcb[33]; /* to zero by compiler) */
/* Structure for linked list of filerefs */
struct file_ref
{
char name[12]; /* File reference */
struct file_ref *next; /* Pointer to next instance */
} root, /* Start of linked list */
*fref_1, /* Scratch pointers to */
*fref_2; /* linked list instances */
/* Initialized file control block for "srch_file()". This FCB
is for a fully ambiguous fileref that causes "srch_file()"
to return all directory entries for the current default
drive. */
static char fcb[] = {'?','?','?','?','?','?','?','?',
'?','?','?','?','?',0,0,0};
int file_cnt = 0, /* Count of file to be backed up */
dup_flag, /* Duplicate fileref flag */
all_files, /* All_files flag (cmd-line option) */
fast_copy, /* Fast copy flag (cmd-line option) */
hard_disk, /* Hard disk flag (cmd-line option) */
query, /* Query flag (cmd-line option) */
system, /* System flag (cmd-line option) */
user_no, /* User number (cmd-line option) */
next_flag = FALSE;/* Flag to indicate to "srch_file()"
that a "search next" is required */
register int i,j; /* Loop indices */
long begin, /* Input file position variables */
end;
/* Display program header */
printf("\nBU Version 1.2");
printf(" Copyright 1985");
printf(" byHeart Software\n\n");
/* Initialize command-line options */
all_files = FALSE; /* Copy only non-archived files */
fast_copy = FALSE; /* Copy files with verification */
hard_disk = FALSE; /* Files will not be split across backup
disks if remaining capacity of backup
disk is less than current file size */
query = FALSE; /* Backup without query */
system = FALSE; /* Assign directory attribute to all
backup files */
user_no = ALL; /* Backup files in all user areas */
/* Parse command line for user-selected options (if any) */
if(argc < 3)
error(BAD_ARGS,NULL); /* Illegal command line */
if(argc > 3)
{
i = 3; /* Start with third command-line argument */
while(i < argc)
{
if(*argv[i] != '-')
error(BAD_OPT,argv[i]); /* Missing leading '-' */
s = argv[i]+1;
while(*s)
{
if(*s == 'A') /* Check for all_files option */
all_files = TRUE;
else if(*s == 'F') /* Check for fast copy option */
fast_copy = TRUE;
else if(*s == 'H') /* Check for hard disk option */
hard_disk = TRUE;
else if(*s == 'Q') /* Check for query option */
query = TRUE;
else if(*s == 'S') /* Check for system option */
system = TRUE;
else if(isdigit(*s)) /* Check for user number option */
{
user_no = *s++ - '0';
if(isdigit(*s))
user_no = user_no * 10 + *s++ - '0';
if(user_no < 0 || user_no > 31)
error(BAD_USER,argv[i]);
continue;
}
else
error(BAD_OPT,argv[i]);
s++;
}
i++;
}
}
/* Validate input parameters */
if(*(argv[1]+1) != '\0') /* Check for specified fileref */
{
if(user_no == ALL) /* Can only use with specified */
error(USER_ERR,NULL); /* user number (-n option) */
/* Modify "fcb[]" to incorporate fileref */
if(copy_fref(fcb,argv[1]) == ERROR)
error(BAD_FREF,argv[1]);
}
if(*argv[1] < 'A' || *argv[1] > 'P' ||
*argv[2] < 'A' || *argv[2] > 'P')
error(BAD_DRV,NULL); /* Illegal drive names */
if(*argv[1] == *argv[2])
error(SAME_DRV,NULL); /* Drive names are same